// @ts-nocheck
// import { createApp } from "vue";// 高阶函数的使用,内部会自动传入dom操作的api
import App from "./App.vue";
import { createRenderer } from '@vue/runtime-dom'
import { isString } from '@/utils/validate'
import { d2a, drawCircle, drawCircleText } from '@/utils/canvas'

let canvas, ctx;
const draw = (el, noClear) => {
  if (!noClear) {
    ctx.clearRect(0, 0, canvas.width, canvas.height)
  }
  if (el.tag === 'circle') {
    let { data, r, x, y } = el;
    let total = data.reduce((memo, current) => memo + current.count, 0);
    let start = 0,
      end = 0;
    data.forEach(item => {
      const proportion = item.count / total;
      end += proportion * 360;
      drawCircle(ctx, start, end, item.color, x, y, r);
      drawCircleText(ctx, item.name, (start + end) / 2, x, y, r - 20);
      drawCircleText(ctx, proportion.toFixed(3) + "%", (start + end) / 2, x - 10, y - 20, r - 20);
      start = end;
    });
  }
  if (el.tag === 'rect') {
    const { data } = el
    const barWidth = canvas.width / 10,
      gap = 20,
      paddingLeft = (data.length * barWidth + (data.length - 1) * gap) / 3,
      paddingBootom = 10;

    data.forEach(({ title, count, color }, index) => {
      const x = paddingLeft + index * (barWidth + gap)
      const y = canvas.height - paddingBootom - count
      ctx.fillStyle = color
      ctx.fillRect(x, y, barWidth, count)
    })
  }

  // 递归
  el.aChild && el.aChild.forEach(child => {
    draw(child, true)
  })
}
const ops: any = {
  /**
   * 3. 插入(由子及父)
   * @param child 
   * @param parent 
   * @param anchor 
   */
  insert: (child: any, parent: any, anchor: any) => {
    // 创建父子关系: 画的时候却是由父到子
    child.parent = parent;
    // 由于Dom的children是只读不可写的;则重新添加一个属性
    if (!parent.aChild) {
      parent.aChild = [child];
    } else {
      parent.aChild.push(child);
    }
    // 父级为canvas(即类型为Element),就把这棵树插入到canvas
    if (parent.nodeType === 1) {
      draw(child)
    }
    console.log('click', child.onClick)
    if (child.onClick) {
      ctx.canvas.addEventListener('click', () => {
        child.onClick();
        setTimeout(() => {
          draw(child)
        }, 0);
      }, false)
    }
  },
  remove: child => {

  },
  /**
   * 1. 创建元素
   * @param tag 
   * @param isSVG 
   * @param is 
   */
  createElement: (tag: string, isSVG: boolean, is: any) => {
    return { tag };
  },
  createText: text => { },
  createComment: text => { },
  setText: (node, text) => {
  },
  setElementText: (el, text) => {
  },
  parentNode: node => { },
  nextSibling: node => { },
  querySelector: selector => { },
  setScopeId(el, id) {
  },
  cloneNode(el) {
    return;
  },
  // __UNSAFE__
  // Reason: innerHTML.
  // Static content here can only come from compiled templates.
  // As long as the user only uses trusted templates, this is safe.
  insertStaticContent(content, parent, anchor, isSVG) {

  },
  /**
   * 2. 原作用: 样式处理和时间处理
   * 针对于canvas: 给canvas描述对象添加属性
   * @param el 
   * @param key 
   * @param prevValue 
   * @param nextValue 
   */
  patchProp(el, key, prevValue, nextValue) {
    // console.log(key, prevValue, nextValue);// x null 300
    el[key] = nextValue;
  }
};

/**
 * vue3的createApp默认是操作Dom的api
 * 目标: 修改为canvas的api
 * @param args 
 */
const createCanvasApp = (...args: any[]) => {
  const app = createRenderer(ops).createApp(...args);
  // 内部默认的mount
  const { mount } = app;
  // 重写mount
  app.mount = function (containerOrSelector: any): any {
    let container;
    if (isString(containerOrSelector)) {
      const res = document.querySelector(containerOrSelector);
      if ((process.env.NODE_ENV !== 'production') && !res) {
        console.warn(`Failed to mount app: mount target selector returned null.`);
      }
      container = res;
    } else {
      container = containerOrSelector;
    }
    canvas = document.createElement('canvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    // [...container.childNodes].forEach(node => {
    //   container.removeChild(node);
    // })
    container.appendChild(canvas);
    ctx = canvas.getContext('2d');
    /* 如果存在,调用原app的count */
    if (container) {
      return mount(container);
    }
  }
  return app;
};

createCanvasApp(App)
  .mount("#app");


